home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tpv24.zip / V24.PAS < prev   
Pascal/Delphi Source File  |  1990-11-23  |  11KB  |  249 lines

  1. (*////////////////////////////////////////////////////////////////////////////
  2. ///                                                                        ///
  3. ///         T U R B O  -  P A S C A L  V24-Interrupt-Support V2.00         ///
  4. ///                (c) Copyright June 1988 by C.Philipps                   ///
  5. ///                                                                        ///
  6. ///               (Turbo Pascal V4.0  or higher required)                  ///
  7. ///                                                                        ///
  8. //////////////////////////////////////////////////////////////////////////////
  9. ///                                                                        ///
  10. ///            Low-level interrupt-handling for the serial ports. Speeds   ///
  11. ///            up to 115200 bps are supportet, one port at a time.         ///
  12. ///            Parts of the basics were taken from Mike Halliday's pop-    ///
  13. ///            ular ASYNC-package (Turbo Pascal 3.0, PD).                  ///
  14. ///                                                                        ///
  15. ///       This module is hereby donated to the public domain.              ///
  16. ///                                                                        ///
  17. ///       Christian Philipps                                               ///
  18. ///       Düsseldorfer Str. 316                                            ///
  19. ///       4130 Moers 1                                                     ///
  20. ///       West-Germany                                                     ///
  21. ///                                                                        ///
  22. ///       Last modified: 07/89                                             ///
  23. ///                                                                        ///
  24. ////////////////////////////////////////////////////////////////////////////*)
  25.  
  26. {$R-,S-,I-,D-,F-,V-,B-,N-,L- }
  27.  
  28. UNIT V24;
  29.  
  30. INTERFACE
  31.  
  32. USES DOS;
  33.  
  34. TYPE   ComType      = (Com1,Com2,Com3,Com4,Com5,Com6);
  35.        BaudType     = (b110,b150,b300,b600,b1200,b2400,b4800,b9600,b19200,
  36.                        b38400,b57600,b115200);
  37.        ParityType   = (Space,Odd,Mark,Even,None);
  38.        DataBitsType = (d5,d6,d7,d8);
  39.        StopBitsType = (s1,s2);
  40.  
  41. CONST  V24Timeout   : BOOLEAN = FALSE;  {SendByte-Timeout}
  42.        IntMasks     : ARRAY[Com1..Com6] OF WORD    = ($EF,$F7,$EF,$F7,$EF,$F7);
  43.        IntVect      : ARRAY[Com1..Com6] OF BYTE    = ($0C,$0B,$0C,$0B,$0C,$0B);
  44.  
  45. VAR    V24TP        : WORD;         {Buffer Tail-Pointer
  46.                                      Im Interface-Teil, da zur Ereignis-
  47.                                      steuerung im Multi-Tasking benötigt.}
  48.        ComBaseAdr   : ARRAY[Com1..Com6] OF WORD;
  49.  
  50. FUNCTION  V24DataAvail:BOOLEAN;
  51. FUNCTION  V24GetByte:BYTE;
  52. PROCEDURE InitCom(ComPort:ComType;Baudrate:BaudType;Parity:ParityType;
  53.                   Bits:DataBitsType;Stop:StopBitsType);
  54. PROCEDURE DisableCom;
  55. PROCEDURE SendByte(Data:BYTE);
  56.  
  57. {=============================================================================}
  58.  
  59. IMPLEMENTATION
  60.  
  61. CONST  Regs       : Registers =
  62.        (AX:0;BX:0;CX:0;DX:0;BP:0;SI:0;DI:0;DS:0;ES:0;FLAGS:0);
  63.        RBR        = $00;          {xF8 Receive Buffer Register            }
  64.        THR        = $00;          {xF8 Transmitter Holding Register       }
  65.        IER        = $01;          {xF9 Interrupt Enable Register          }
  66.        IIR        = $02;          {xFA Interrupt Identification Register  }
  67.        LCR        = $03;          {xFB Line Control Register              }
  68.        MCR        = $04;          {xFC Modem Control Register             }
  69.        LSR        = $05;          {xFD Line Status Register               }
  70.        MSR        = $06;          {xFE Modem Status Register              }
  71.                                   {--- if LCR Bit 7 = 1  ---              }
  72.        DLL        = $00;          {xF8 Divisor Latch Low Byte             }
  73.        DLH        = $01;          {xF9 Divisor Latch Hi  Byte             }
  74.        CMD8259    = $20;          {Interrupt Controller Command Register  }
  75.        IMR8259    = $21;          {Interrupt Controller Mask Register     }
  76.                                   {Should be evaluated by any higher-level
  77.                                    send-routine}
  78.        LoopLimit  = 1000;         {When does a timeout-error occur        }
  79.        V24BuffSize= 2048;         { Ringpuffer 2 KB }
  80.  
  81. VAR    BiosComBaseAdr : ARRAY[Com1..Com2] OF WORD ABSOLUTE $0040:$0000;
  82.        ActivePort : ComType;
  83.        { The Com-Port base adresses are taken from the BIOS data area }
  84.        ComBase    : WORD;         {Hardware Com-Port Base Adress          }
  85.        OldV24     : Pointer;
  86.        V24HP      : WORD;         {Buffer Head-Pointer                    }
  87.        V24BuffEnd : WORD;         {Buffer End-Adress                      }
  88.        V24Buff    : ARRAY[0..V24BuffSize] OF BYTE;
  89.        OExitHandler : Pointer;    {Save-Area für Zeiger auf Org.-Exit-Proc}
  90.  
  91. {============================ lokale Routinen ================================}
  92.  
  93. PROCEDURE V24Int; external;
  94. {$L v24.obj}
  95.  
  96. {-----------------------------------------------------------------------------}
  97.  
  98. PROCEDURE ClearPendingInterrupts;
  99.  
  100. VAR  N : BYTE;
  101.  
  102. BEGIN {ClearPendingInterrupts}
  103.   WHILE (PORT[ComBase+IIR] AND 1) = 0 DO  {While Interrupts are pending}
  104.   BEGIN
  105.     N := PORT[ComBase+LSR];               {Read Line Status}
  106.     N := PORT[ComBase+MSR];               {Read Modem Status}
  107.     N := PORT[ComBase+RBR];               {Read Receive Buffer Register}
  108.     PORT[CMD8259] := $20;                 {End of Interrupt}
  109.   END;
  110. END;  {ClearPendingInterrupts}
  111.  
  112. {======================== extern verfügbare Routinen =========================}
  113.  
  114. FUNCTION V24DataAvail:BOOLEAN;
  115.  
  116. { This function checks, whether there are characters in the buffer }
  117.  
  118. BEGIN {V24DataAvail}
  119.   V24DataAvail := (V24HP <> V24TP);
  120. END;  {V24DataAvail}
  121.  
  122. {-----------------------------------------------------------------------------}
  123.  
  124. FUNCTION V24GetByte:BYTE;
  125.  
  126. { Take a byte out of the ring-buffer and return it to the caller.
  127.   This function assumes, that the application has called V24DataAvail
  128.   before to assure, that there are characters available!!!!
  129.   The ISR only reads the current head-pointer value, so this routine
  130.   may modify the head-pointer with interrupts enabled. }
  131.  
  132. BEGIN {V24GetByte}
  133.   V24GetByte := Mem[DSeg:V24HP];
  134.   Inc(V24HP);
  135.   IF V24HP > V24BuffEnd
  136.      THEN V24HP := Ofs(V24Buff);
  137. END;  {V24GetByte}
  138.  
  139. {-----------------------------------------------------------------------------}
  140.  
  141. PROCEDURE SendByte(Data:BYTE);
  142.  
  143. VAR   Count:BYTE;
  144.  
  145. BEGIN {SendByte}
  146.   Count := 0;
  147.   V24Timeout := FALSE;
  148.   IF ComBase > 0
  149.      THEN BEGIN
  150.             REPEAT
  151.               Count := SUCC(Count);
  152.             UNTIL ((PORT[ComBase+LSR] AND $20) <> 0) OR (Count > LoopLimit);
  153.             IF Count > LoopLimit
  154.                THEN V24Timeout := TRUE
  155.                ELSE PORT[ComBase+THR] := Data;
  156.           END;
  157. END;  {SendByte}
  158.  
  159. {-----------------------------------------------------------------------------}
  160.  
  161. PROCEDURE InitCom(ComPort:ComType;Baudrate:BaudType;Parity:ParityType;
  162.                   Bits:DataBitsType;Stop:StopBitsType);
  163.  
  164. CONST BaudConst   : ARRAY[b110..b115200] OF WORD =
  165.                     ($417,$300,$180,$C0,$60,$30,$18,$0C,$06,$03,$02,$01);
  166.       ParityConst : ARRAY[Space..None] OF BYTE =
  167.                     ($38,$08,$28,$18,$00);
  168.       BitsConst   : ARRAY[d5..d8] OF BYTE =
  169.                     ($00,$01,$02,$03);
  170.       StopConst   : ARRAY[s1..s2] OF BYTE =
  171.                     ($00,$04);
  172.  
  173. BEGIN {InitCom}
  174.   V24HP       := Ofs(V24Buff);
  175.   V24TP       := V24HP;
  176.   V24BuffEnd  := V24HP+V24BuffSize;
  177.   FillChar(V24Buff,Succ(V24BuffSize),#0);
  178.   V24Timeout := FALSE;                             {Reset Timeout-Marker}
  179.   ComBase := ComBaseAdr[ComPort];                  {Get Com-Port base adress}
  180.   ActivePort := ComPort;                           {Keep Active-Port for EOI}
  181.   ClearPendingInterrupts;
  182.   GetIntVec(IntVect[ComPort],OldV24);
  183.   SetIntVec(IntVect[ComPort],@V24Int);
  184.                                                    {Install interrupt routine}
  185.   INLINE($FA);                                     {CLI}
  186.   PORT[ComBase+LCR] := $80;                        {Adress Divisor Latch}
  187.   PORT[ComBase+DLH] := Hi(BaudConst[Baudrate]);    {Set Baud rate}
  188.   PORT[COMBase+DLL] := Lo(BaudConst[Baudrate]);
  189.   PORT[ComBase+LCR] := ($00 OR ParityConst[Parity] {Setup Parity}
  190.                             OR BitsConst[Bits]     {Setup number of databits}
  191.                             OR StopConst[Stop]);   {Setup number of stopbits}
  192.   PORT[ComBase+MCR] := $0B;                        {Set RTS,DTR,OUT2}
  193. (*
  194.   PORT[ComBase+MCR] := $1B;                        {Set RTS,DTR,OUT2,Loop}
  195. *)
  196.   PORT[ComBase+IER] := $01;                        {Enable Data-Available Interrupts}
  197.   PORT[IMR8259] := PORT[IMR8259] AND IntMasks[ComPort]; {Enable V24-Interrups}
  198.   INLINE($FB);                                     {STI}
  199. END;  {InitCom}
  200.  
  201. {-----------------------------------------------------------------------------}
  202.  
  203. PROCEDURE DisableCom;
  204.  
  205. BEGIN {DisableCom}
  206.   IF ComBase = 0
  207.      THEN Exit;
  208.   INLINE($FA);                                     {CLI}
  209.   PORT[ComBase+MCR] := 00;                         {Disable Interrupts, Reset MCR}
  210.   PORT[IMR8259] := PORT[IMR8259] OR $18;           {Disable Interrupt Level 3 and 4}
  211.   PORT[ComBase+IER] := 0;                          {Disable 8250-Interrupts}
  212.   ClearPendingInterrupts;                          {Clean up}
  213.   ComBase := 0;                                    {Reset Combase}
  214.   SetIntVec(IntVect[ActivePort],OldV24);           {Reset old IV}
  215.   INLINE($FB);                                     {STI}
  216. END;  {DisableCom}
  217.  
  218. {-----------------------------------------------------------------------------}
  219.  
  220. {$F+}
  221. PROCEDURE V24ExitProc;
  222.  
  223. BEGIN {V24ExitProc}
  224.   DisableCom;
  225.   ExitProc := OExitHandler;                 { alten Exit-Handler reaktivieren }
  226. END;  {V24ExitProc}
  227. {$F-}
  228.  
  229. {-----------------------------------------------------------------------------}
  230.  
  231. BEGIN {Initialisation}
  232.   {Grund-Init, damit irrtümliche Aufrufe von V24DataAvail nicht zu
  233.    endlosen Ausgaben von Speicherschrott führen!}
  234.   Move(BiosComBaseAdr,ComBaseAdr[Com1],SizeOf(BiosComBaseAdr));
  235.   Move(BiosComBaseAdr,ComBaseAdr[Com3],SizeOf(BiosComBaseAdr));
  236.   Move(BiosComBaseAdr,ComBaseAdr[Com5],SizeOf(BiosComBaseAdr));
  237.   ComBase     := 0;
  238.   V24HP       := Ofs(V24Buff);
  239.   V24TP       := V24HP;
  240.   V24BuffEnd  := V24HP+V24BuffSize;
  241.  
  242.   OExitHandler := ExitProc;
  243.   ExitProc     := @V24ExitProc;
  244. END.  {Initialisation}
  245.  
  246. (*////////////////////////////////////////////////////////////////////////////
  247. ///                       E N D   O F   M O D U L E                        ///
  248. ////////////////////////////////////////////////////////////////////////////*)
  249.